package com.hexacta.hrs.repositories.impl;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.vectrics.employee.Employee;

import com.hexacta.hrs.domain.staffing.Project;
import com.hexacta.hrs.domain.staffing.Requirement;
import com.hexacta.hrs.domain.staffing.assignment.EmployeeAssignment;
import com.hexacta.hrs.repositories.ProjectRepository;

/**
 * 
 * @author nscuri
 *
 */
public class ProjectRepositoryHibernateTemplateImpl extends HibernateRecordObjectRepository<Project> implements ProjectRepository {

	public ProjectRepositoryHibernateTemplateImpl(Class<Project> entityClass) {
		super(entityClass);
	}
	
	public void saveOrUpdate(Object o) {
        this.save((Project)o);
    }

	public Project findById(long id) {
    	return this.forId(id);
    }

	@SuppressWarnings("unchecked")
	public List<Project> findAll() {
    	return (List<Project>) this.all();
    }
	
	@Override
	public List<Employee> findRequirementResults(Requirement requirement) {
		Criteria assignment = getSession().createCriteria(EmployeeAssignment.class);
		assignment.setProjection(Projections.property("employee"));
		assignment.setProjection(Projections.distinct(Projections.property("employee")));

		Calendar startDate = Calendar.getInstance(); 
		startDate.setTime(requirement.getStartDate().getTime());
		startDate.add(Calendar.MONTH, +2);
		assignment.add(Restrictions.le("endDate", startDate ));
		
		Criteria employee = getSession().createCriteria(Employee.class);
		employee.add(Restrictions.isNull("dateEnd"));
		
		Criteria function = employee.createCriteria("function");
		function.add(Restrictions.and((Restrictions.gt("weight", requirement.getRequiredRol().getWeight()-2)), 
				Restrictions.lt("weight", requirement.getRequiredRol().getWeight()+2)));
		function.add(Restrictions.gt("weight", 0));
		
		Criteria functionType = function.createCriteria("JobFunctionType");
		functionType.add(Restrictions.eq("area", requirement.getRequiredRol().getJobFunctionType().getArea()));
		
		assignment.add(Restrictions.in("employee", employee.list()));
		return assignment.list();
	}

	@Override
	public List<Project> search(Map<String, Object> filters) {
		Criteria crit = getSession().createCriteria(Project.class, "project");

		if (filters != null && !filters.isEmpty()) {
			filters.remove("dateFrom");
			filters.remove("dateTo");
			filters.remove("showInternal");
        

//            Calendar dFrom = (Calendar) filters.get("dateFrom");
//            if (dFrom != null) {
//                crit.add(Restrictions.ge("project.dateStart", dFrom));
//            }
//            Calendar dTo = (Calendar) filters.get("dateTo");
//            if (dTo != null) {
//                crit.add(Restrictions.lt("project.dateEnd", dTo));
//            }

//            // Ultima reunion realizada
//            Boolean lastMeeting = (Boolean) parameters.get("lastMeeting");
//            if (lastMeeting != null && lastMeeting.equals(true) && roundedDateTo != null) {
//                crit.add(Restrictions.lt("meeting.date", roundedDateTo));
//            }
//
//            // Mes proxima reunion
//            Integer month = (Integer) parameters.get("monthNextMeeting");
//            if (month != null) {
//                crit.add(Restrictions.eq("meeting.date.month", month));
//            }
//
//            // Filtro por status (MeetingStatus)
//            MeetingStatus status = (MeetingStatus) parameters.get("status");
//            if (status != null) {
//                crit.add(Restrictions.eq("meeting.status", status));
//            }
//
            // Filtro por checkedByHR
          
//
//            // Filtro por delayed: las primeras meetings que no han tenido
//            // alguna anterior nunca van a estar demoradas
//            Boolean delayed = (Boolean) parameters.get("onlyDelayed");
//            if (delayed != null && delayed.equals(true)) {
//                crit.add(Restrictions.isNotNull("meeting.previousMeeting"));
//            }
        }
//
//        // Filtro por las relaciones mentor/mentorado activas
//        if (filters.containsKey("onlyCurrentRelationships")
//                && ((Boolean) parameters.get("onlyCurrentRelationships"))) {
//            crit.createCriteria("meeting.employee", "e").add(
//                    Restrictions.eqProperty("e.mentor.id", "meeting.mentor.id"));
//        }
//        crit.addOrder(Order.desc("meeting.date"));

        // Se devuelven los filtros.
        return crit.list();
	}

	/* (non-Javadoc)
	 * @see com.hexacta.hrs.repositories.ProjectRepository#searchByName(java.lang.String)
	 */
	@Override
	public Project searchByName(String name) {
		Criteria crit = getSession().createCriteria(Project.class, "project");
		crit.add(Restrictions.eq("project.name",name));
		return (Project) crit.uniqueResult();
	}
}
